//
//  CLocator.m
//  HCHK_iphone
//
//  Created by yilong zhang on 12-1-5.
//  Copyright 2012年 __MyCompanyName__. All rights reserved.
//

#import "CLocator.h"

//=================================================================================================================

@implementation CAddrInfo

@synthesize m_strSum;
@synthesize m_strCountry;
@synthesize m_strProvince;
@synthesize m_strCity;
@synthesize m_fX;
@synthesize m_fY;

-(id)init
{
    self = [super init];
    if (self)
    {
        self.m_strCity      = @"";
        self.m_strProvince  = @"";
        self.m_strCountry   = @"";
        self.m_strSum       = @"";
        self.m_fX           = 0.000000;
        self.m_fY           = 0.000000;
    }
    
    return self;
}

-(void)dealloc
{
    self.m_strCity      = nil;
    self.m_strProvince  = nil;
    self.m_strCountry   = nil;
    self.m_strSum       = nil;
    
    [super dealloc];
}

@end


//=================================================================================================================

@implementation CLocator

static CLocator *g_Instance = nil;

@synthesize m_LocationManager;
@synthesize m_bIsLocationOpen;
@synthesize m_Coordinate2D;
@synthesize m_Data;
@synthesize m_AddrInfo;
@synthesize m_Timer;
@synthesize m_bIsCheckNetState;
@synthesize m_nNetState;
@synthesize m_fUpdateDistance;
@synthesize m_bIsForcedLocal;

+(id)allocWithZone:(NSZone *)zone
{
    @synchronized(self)
    {
        if (!g_Instance)
        {
            g_Instance = [super allocWithZone:zone];
        }
    }
    
    return g_Instance;
}

+(CLocator*)DefaultLocator
{
    if (!g_Instance)
    {
        g_Instance = [[CLocator alloc] init];
    }
    
    return g_Instance;
}

+(void)DestroyLocator
{
    if ([g_Instance retainCount])
    {
        [g_Instance release];
        g_Instance = nil;
    }
}

- (id)init
{
    self = [super init];
    if (self)
    {
        m_LocationManager = [[CLLocationManager alloc] init];
        m_LocationManager.desiredAccuracy= kCLLocationAccuracyBest;
        
        m_bIsLocationOpen = NO;
        m_bIsForcedLocal  = NO;
        m_bIsCheckNetState= YES;
        m_nNetState       = 0;
        m_fUpdateDistance = 500.0f;
        
        m_AddrInfo = [[CAddrInfo alloc] init];
        m_AddrInfo.m_fX = 0.000000;
        m_AddrInfo.m_fY = 0.000000;
        m_AddrInfo.m_strCity    = nil;
        m_AddrInfo.m_strCountry = nil;
        m_AddrInfo.m_strProvince= nil;
        m_AddrInfo.m_strSum     = nil;
        
        m_Coordinate2D.latitude = 0.000000;
        m_Coordinate2D.longitude= 0.000000;
    }
    
    return self;
}

-(void)dealloc
{
    [m_LocationManager release];
    [m_Data release];
    [m_AddrInfo release];
    
    [super dealloc];
}

-(int)CheckNetState
{
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;
    
    SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
    SCNetworkReachabilityFlags flags;
    
    BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
    CFRelease(defaultRouteReachability);
    
    if (!didRetrieveFlags)
    {
        return NO;
    }
    
    BOOL isReachable = flags & kSCNetworkFlagsReachable;
    BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
    (isReachable && !needsConnection) ? (m_nNetState = 1) : (m_nNetState = 0);
    
    return m_nNetState;
}

-(int)CheckDevLocation
{
    //监测设备是否支持定位
    if (![CLLocationManager locationServicesEnabled])
    {
        return DevNotSupport;
    }
    
    //网络可用情况下定位
    if (0 == [self CheckNetState])
    {
        return NetNotSupport;
    }
    
    //没有定位使用权限
    if (kCLAuthorizationStatusDenied == [CLLocationManager authorizationStatus])
    {
        return AuthNotSupport;
    }
    
    return NormalSupport;
}

-(int)StartLocation
{    
    LocalRet Ret = NormalSupport;
    if (NormalSupport != (Ret = [self CheckDevLocation]))
    {
        return Ret;
    }
    
    //启动定位
    //停止上次定位
    [self StopLocation];
    m_LocationManager.delegate = self;
    [m_LocationManager startUpdatingLocation];
    m_Timer = [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:@selector(WaitLoactionRetTimeout:) userInfo:nil repeats:NO];
    m_bIsLocationOpen = YES;
    
    return Ret;
}

-(void)WaitLoactionRetTimeout:(NSTimer*)timer
{
    if (m_Timer)
    {
        m_Timer = nil;
        
        [self StopLocation];
        
        /*m_AddrInfo.m_fX = 0.000000;
        m_AddrInfo.m_fY = 0.000000;
        m_AddrInfo.m_strCity    = nil;
        m_AddrInfo.m_strCountry = nil;
        m_AddrInfo.m_strProvince= nil;
        m_AddrInfo.m_strSum     = nil;*/
        NSLog(@"\r\n\r\n定位超时\r\n\r\n");
    
        [[NSNotificationCenter defaultCenter] postNotificationName:MSG_LOCATION_TIMEOUT object:nil];
    }
}

-(void)StopLocation
{
    m_LocationManager.delegate = nil;
    [m_LocationManager stopUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager
	didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{
    [self StopLocation];
    
    //两次的经纬度距离大于某个值测重新坐标解析
    if ([newLocation distanceFromLocation:oldLocation] > m_fUpdateDistance || nil == oldLocation || m_bIsForcedLocal)
    {
        [self GetAddressInfoWithParams:zhHans Coordinate:newLocation.coordinate];
    }
    else
    {
        m_Timer = nil;
        //发送本地定位成功通知,将前一次的信息返回
        [[NSNotificationCenter defaultCenter] postNotificationName:MSG_LOCATION_RET object:m_AddrInfo];
    }
    
    m_bIsForcedLocal = NO;
}

-(void)GetAddressInfoWithParams:(Language)language Coordinate:(CLLocationCoordinate2D)coordinate
{
    if (!m_Timer)
    {
        m_Timer = [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:@selector(WaitLoactionRetTimeout:) userInfo:nil repeats:NO];
    }
    
    NSString *strlanguage = nil;
    
    if (zhHans == language)
    {
        strlanguage = [NSString stringWithString:@"ZH"];
    }
    else 
    {
        strlanguage = [NSString stringWithString:@"ZH"];
    }
    
    m_Data = [NSMutableData data];
    [m_Data retain];
    
    m_Coordinate2D.longitude = coordinate.longitude;    //140.388314;
    m_Coordinate2D.latitude  = coordinate.latitude;     //35.762698;
        
    NSString *request = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=true&language=%@", coordinate.latitude, coordinate.longitude, strlanguage];
        
    NSMutableURLRequest *m_UrlRequest = [[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:request]] autorelease];
    [m_UrlRequest setHTTPMethod:@"GET"];
        
    NSURLConnection *m_UrlConnection = [[[NSURLConnection alloc] initWithRequest:m_UrlRequest delegate:self] autorelease];
    [m_UrlConnection start];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    //
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [m_Data appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{   
    m_Timer = nil;

    NSString *json = [[NSString alloc] initWithData:m_Data encoding:NSUTF8StringEncoding];
    NSDictionary *dic  = [json JSONValue];
    
   if ([[dic objectForKey:@"status"] isEqualToString:@"OK"])
   {       
        NSArray *addresses = [dic objectForKey:@"results"];
        
        if (addresses)
        {
            NSString *string= nil;
            
            self.m_AddrInfo.m_strCity     = nil;
            self.m_AddrInfo.m_strProvince = nil;
            self.m_AddrInfo.m_strCountry  = nil;
            self.m_AddrInfo.m_strSum      = nil;
            self.m_AddrInfo.m_fX = m_Coordinate2D.latitude;
            self.m_AddrInfo.m_fY = m_Coordinate2D.longitude;
            
            for (NSDictionary *sub in addresses)
            {
                //概述
                if (!self.m_AddrInfo.m_strSum)
                    self.m_AddrInfo.m_strSum = [sub objectForKey:@"formatted_address"];
                //城市，省份，国家
                dic = [sub objectForKey:@"address_components"];
                for (NSDictionary *subb in dic) 
                {
                    if ([[subb objectForKey:@"types"] count] > 0)
                    {
                        string = [[subb objectForKey:@"types"] objectAtIndex:0];
                        if ([string isEqualToString:@"locality"])
                        {
                            if (!self.m_AddrInfo.m_strCity)
                                self.m_AddrInfo.m_strCity = [subb objectForKey:@"long_name"];
                        }
                        else if ([string isEqualToString:@"country"])
                        {
                            if (!self.m_AddrInfo.m_strCountry)
                                self.m_AddrInfo.m_strCountry = [subb objectForKey:@"long_name"];
                        }
                        else if ([string isEqualToString:@"administrative_area_level_1"])
                        {
                            if (!self.m_AddrInfo.m_strProvince)
                                self.m_AddrInfo.m_strProvince = [subb objectForKey:@"long_name"];
                        }
                        else {;}
                    }
                }
            }
            [m_Data release];
            m_Data = nil;
            
            //城市为空的情况下，设置城市，特殊情况
            if (nil == self.m_AddrInfo.m_strCity)
            {
                if (self.m_AddrInfo.m_strProvince)
                {
                    self.m_AddrInfo.m_strCity = self.m_AddrInfo.m_strProvince;
                }
                else if (m_AddrInfo.m_strCountry)
                {
                    self.m_AddrInfo.m_strCity = self.m_AddrInfo.m_strCountry;
                }
                else {;}
            }
            //省份
            if (nil == self.m_AddrInfo.m_strProvince)
            {
                self.m_AddrInfo.m_strProvince = self.m_AddrInfo.m_strCountry;
            }
            
            //NSLog(@"\r\n\r\n谷歌对(Latitude:%f,Longtitude:%f)的解析结果:City:%@__Province:%@__Country:%@__(Latitude:%f__Longtitude:%f)\r\n\r\n", m_AddrInfo.m_fX, m_AddrInfo.m_fY, m_AddrInfo.m_strCity, m_AddrInfo.m_strProvince, m_AddrInfo.m_strCountry, m_AddrInfo.m_fX, m_AddrInfo.m_fY);
            
            [[NSNotificationCenter defaultCenter] postNotificationName:MSG_LOCATION_RET object:self.m_AddrInfo];
        }
        else 
        {
            [[NSNotificationCenter defaultCenter] postNotificationName:MSG_LOCATION_RET object:nil];
        }
   }
   //谷歌拒绝访问
   else 
   {     
       NSLog(@"\r\n\r\n<--------谷歌拒绝地址解析-------->\r\n\r\n");
       [[NSNotificationCenter defaultCenter] postNotificationName:MSG_LOCATION_RET object:nil];
   }
    
   [json release];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{   
    m_Timer = nil;
    
    /*m_Coordinate2D.latitude = 0.000000;
    m_Coordinate2D.longitude= 0.000000;
    
    m_AddrInfo.m_fX = 0.000000;
    m_AddrInfo.m_fY = 0.000000;
    m_AddrInfo.m_strCity    = nil;
    m_AddrInfo.m_strCountry = nil;
    m_AddrInfo.m_strProvince= nil;
    m_AddrInfo.m_strSum     = nil;*/
    NSLog(@"\r\n\r\nconnection:didFailWithError\r\n\r\n");
    
    [[NSNotificationCenter defaultCenter] postNotificationName:MSG_LOCATION_RET object:nil];
}

- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error
{
    m_Timer = nil;

    /*m_Coordinate2D.latitude = 0.000000;
    m_Coordinate2D.longitude= 0.000000;
    
    m_AddrInfo.m_fX = 0.000000;
    m_AddrInfo.m_fY = 0.000000;
    m_AddrInfo.m_strCity    = nil;
    m_AddrInfo.m_strCountry = nil;
    m_AddrInfo.m_strProvince= nil;
    m_AddrInfo.m_strSum     = nil;*/
    NSLog(@"\r\n\r\nlocationManager:didFailWithError\r\n\r\n");
    
    [[NSNotificationCenter defaultCenter] postNotificationName:MSG_LOCATION_RET object:nil];

    [self StopLocation];
}

@end
